﻿#include<iostream>
using namespace std;
const int N = 100010;
int son[N][26], cnt[N], idx;
char str[N];

void insert(char str[])//主参数：str函数名，形参：char str[]
{
    int p = 0;
    for (int i = 0; str[i]; i++)//str[i]:字符串，最后一位是'\0'
    {
        int u = str[i] - 'a';//转为数字
        if (!son[p][u])  son[p][u] = ++idx;//没有的话添加进来
        p = son[p][u];//有的话就继续找
    }
    cnt[p]++;
}
int query(char str[])
{
    int p = 0;
    for (int i = 0; str[i]; i++)
    {
        int u = str[i] - 'a';
        if (!son[p][u])  return 0;
        //else    return cnt[p];
        p = son[p][u];//这个还没找到最后一个字符呢，继续找
        //return cnt[p];
    }
    return cnt[p];//最后打印
}
int main()
{
    int n;
    cin >> n;
    //while(cin>>n,n)这种用的情况是未知操作次数
    while (n--)
    {
        char op;//cin>>op在循环里面，先op再str的顺序
        cin >> op >> str;//str函数名代表函数首地址入口，这样就可以
        if (op == 'I') insert(str);
        else    cout << query(str) << endl;
    }
    return 0;
}

/*1.'\0'的ascii就是0
 char a ='\0';  char b = '0';   printf("a = %d,b = %d\n",a,b);
 a = 0,b = 48
for(int i=0;str[i];i++) :str[i]作为判断条件与if(str[i])是一样的效果（我自己理解的）
写成for(..;str[i]!='\0';..)是一样的

2.函数这个使用还是有点不熟练啊
主函数内：
char str[N];
cin>>str;
fun(str)这样就可以
然后形参fun(char str[])
也可以char str[N]全局变量，主函数内cin>>str; 不传参fun()内直接使用str[i]

3.这个代码思路的理解，难理解的点是：
for(..)
   {
【0】      int u = str[i] - 'a';//转为数字
【1】      if (!son[p][u])  son[p][u] = ++idx;//没有的话添加进来
【2】      p = son[p][u];//有的话就继续找
    }
    cnt[p]++;
    
这部分代码，其中第0行，就是讲a-z=>0-25映射为数字
第1行是没有该节点就添加，添加的方式是添加该节点的编号
idx理解为每个节点的唯一编号，有了该节点就不需要再编号，
后面对字符串的统计，实质也是通过访问节点的编号cnt[p]
第2行就是在该路径下沿着串继续找

4.++idx而不是idx++
此时son[0][49]==0 ，哎~，这就导致判断被打断了,直接去执行return 0
idx把0给了根，1给了son[0][x],第一个节点是0的话query查询返回值

以如下测试用例举例：
2
I a
Q a
此时，
son[0][0]=0;
p=0;
cnt[0]=1;插入是没问题的，可是在查询的时候
执行if(!son[q][u]) return 0;是没办法判断是否存在，因为son[0][0]=0，return出去了
*/